<?php
  /**
   * This class is a wrapper for the HTMLPurifier class
   *
   * @author Macdonald Terrence Robinson
   * @package Core
   *
   */

  require_once dirname(__FILE__).'/htmlpurifier/HTMLPurifier.standalone.php';

  final class XSS
  {    
    private static $htmlPurifier = NULL;

    public static function init()
    {
      $config = HTMLPurifier_Config::createDefault();

      $config->set('Core.Encoding',  Config::$charset ); // replace with your encoding
      $config->set('HTML.Doctype', 'XHTML 1.0 Transitional'); // replace with your doctype
      $config->set('Cache.SerializerPath', Config::$siteDir.Config::$writableDir.'htmlfilter/');
      $config->set("HTML.SafeEmbed", true);
      $config->set("HTML.SafeObject", true);
      $config->set("HTML.SafeObject", true);

      $config->set('HTML.DefinitionID', 'MacsFramework-HTMLPurifierDefinitionID');
      $config->set('Cache.DefinitionImpl', null); // remove this later!

      $def = $config->getHTMLDefinition(true);
      
      $def->addAttribute('a', 'target', new HTMLPurifier_AttrDef_Enum(
        array('_blank','_self','_target','_top')
      ));

      $def->addAttribute('*', 'name', 'CDATA');
      
      $def->addAttribute('a', 'name', 'CDATA');
      $def->addAttribute('img', 'usemap', 'CDATA');

      $def->addElement(
        'map',   // name of the element
        'Block',
        'Flow', // no children elements are allowed
        'Common', // common attributes like style/class/id
        array( // attributes
          'name*' => 'CDATA',
          'id' => 'CDATA',
        )
      );

      $def->addElement(
        'area',   // name of the element
        'Inline',
        'Flow',
        'Empty', // common attributes like style/class/id
        array(
          'coords*' => 'CDATA',
          'shape*'  => 'CDATA',
          'target'  => 'CDATA',
          'href'    => 'CDATA',
          'title'   => 'CDATA',
          'alt'     => 'CDATA'
        )
      );
      
      $def->addElement(
        'video',   // name of the element
        'Inline',  // inline element, just as  or
        'Empty', // no children elements are allowed
        'Common', // common attributes like style/class/id
        array( // attributes
          'src*' => 'URI',
        )
      );

      self::$htmlPurifier = new HTMLPurifier($config);
    }
    
    public static function setAllowedTags(array $tags)
    {
      self::$allowedTags = $tags;
    }
    
    public static function getAllowedTags()
    {
      return self::allowedTags;
    }
    
    public static function cleanString( $string, $purify=true, $removeStrings=array(), $stripTags=false )
    {      
      $string = urldecode($string);      
      $string = trim(str_ireplace(array('&lt;script&gt;', '&lt;/script&gt;','script&gt;', '<script>', '<script', 'script>', '</script>', '<?', '?>','<#', '<%', '<!'), array(''), $string));

      if(strlen($string) == strlen(strip_tags($string)))
        $string = str_replace(array("'+",'<','>',')+',"='",'";',';</'), array(''), $string);
      
      if($stripTags)
        $string = strip_tags($string);
      
      if( count($removeStrings) > 0)
        $string = str_ireplace($removeStrings, array(''), $string);

      if($purify)
        $string = self::$htmlPurifier->purify($string);
      
      return $string;
    }

    public static function cleanArray( array $array, $removeStrings=array() )
    {
      $stripTags = false;
      
      foreach ($array as $key=>$value)
      {
        if(($key === 'GLOBALS') || ( stristr($key, 'Pagination_') ))
          continue;
          
        if(is_array($value))
          $array[$key] = self::cleanArray($value, $removeStrings);
        else if(is_string($value))
        {
          unset($array[$key]);

          $value = stripslashes($value);

          $key = self::cleanString($key, $removeStrings);
          $value = self::cleanString($value, $removeStrings);
          $array[$key] = $value;
        }
      }
      return $array;
    }
    
    public static function clean($value)
    {
      if( is_array($value) && count($value) > 0 )
        return self::cleanArray($value);
      else if( is_string($value) && trim($value) != '' )
        return self::cleanString($value);
      else
        return $value;
    }

    public static function cleanGlobalKeys(array $globalKeys)
    {
      foreach ($globalKeys as $key=>$value)
        $GLOBALS[$value] = self::clean($GLOBALS[$value]);
    }
  }
?>
